<?php
declare(strict_types=1);
/**
 * MineAdmin is committed to providing solutions for quickly building web applications
 * Please view the LICENSE file that was distributed with this source code,
 * For the full copyright and license information.
 * Thank you very much for using MineAdmin.
 *
 * @Author X.Mo<root@imoi.cn>
 * @Link   https://gitee.com/xmo/MineAdmin
 */

namespace Plugin\Alarm\Service;

use App\Service\IService;
use Common\Common;
use Hyperf\Collection\Arr;
use Hyperf\Coroutine\Coroutine;
use Plugin\Alarm\Repository\RdAlarmMsgRepository;
use Plugin\Alarm\Repository\RdAlarmTypeRepository;
use Plugin\File\Repository\RdFilePlaybackVideoRepository;
use Psr\Log\LogLevel;

/**
 * 报警事件回调服务类
 */
final class RdAlarmMsgService extends IService
{
    public function __construct(
        protected readonly RdAlarmMsgRepository          $repository,
        protected readonly RdAlarmWarnRecordService      $warnRecordService,
        protected readonly RdFilePlaybackVideoRepository $playbackVideoRepository,
        protected readonly RdAlarmTypeRepository         $alarmTypeRepository
    )
    {
    }

    public function callback(array $data)
    {
        Common::log(__CLASS__, 'alarm message : ' . json_encode($data));
        if (!Arr::get($data, 'yj_data_id')) {
            $msg = $this->cameraCallback($data);
            $time = intval($data['timestamp']) ?? time();
        } else {
            if (Arr::get($data, 'type') == 2) {
                return $this->radarVideo($data);
            } else {
                $msg = $this->radarImg($data);
                $time = time();
            }
        }
        unset($data);
        if ($msg) {
            if (Coroutine::create($this->warnRecordService->warn($msg, $time)) == -1) {
                Common::log(__CLASS__, 'alarm msg_id: ' . $msg['id'] . ' warnRecordService error', LogLevel::WARNING);
            }
        }
        return true;
    }

    private function cameraCallback($data): array | bool
    {
        // 创建年月日目录结构
        $dateDir = date('Ymd', time());

        // 创建报警图片存储目录
        $alarmImgDir = BASE_PATH . '/storage/alarm/alarm_img/' . $dateDir;

        // 创建源图片存储目录
        $srcImgDir = BASE_PATH . '/storage/alarm/src_img/' . $dateDir;

        // 处理报警图片
        $alarmPicPath = '';
        $alarmPicName = '';
        if (Arr::get($data, 'alarmPicData')) {
            // 使用Common类方法保存报警图片
            $alarmFileInfo = Common::saveBase64Image(
                $data['alarmPicData'],
                $alarmImgDir,
                $data['alarmPicName'] ?? ''
            );
            $alarmPicPath = 'alarm/alarm_img/' . $dateDir . '/' . $alarmFileInfo['name'];
            $alarmPicName = $alarmFileInfo['name'];
        }

        // 处理源图片
        $srcPicPath = '';
        $srcPicName = '';
        if (Arr::get($data, 'srcPicData')) {
            // 使用Common类方法保存源图片
            $srcFileInfo = Common::saveBase64Image(
                $data['srcPicData'],
                $srcImgDir,
                $data['srcPicName'] ?? ''
            );
            $srcPicPath = 'alarm/src_img/' . $dateDir . '/' . $srcFileInfo['name'];
            $srcPicName = $srcFileInfo['name'];
        }

        // 存储数据到数据库 (使用与数据库表结构匹配的字段)
        $insert = $this->create([
            'type' => 2,
            'alarm_pic_path' => $alarmPicPath,
            'alarm_pic_name' => $alarmPicName,
            'camera_id' => $data['cameraId'] ?? null,
            'camera_url' => $data['cameraUrl'] ?? null,
            'image_height' => $data['imageHeight'] ?? null,
            'image_width' => $data['imageWidth'] ?? null,
            'result_data' => $data['resultData'] ?? null,
            'roi' => $data['roi'] ?? null,
            'src_pic_path' => $srcPicPath,
            'src_pic_name' => $srcPicName,
            'task_id' => $data['taskId'] ?? null,
            'timestamp' => $data['timestamp'] ?? null,
        ]);
        return [
//            @todo 确定字段
            'type' => $this->getType(strval($data['resultData']['classId']), 2),
            'device_serial' => substr($data['cameraUrl'], strlen('rtsp://'), 20),
            'channel_no' => explode('.', explode('_', $data['cameraUrl'])[1])[0],
            'id' => $insert->id
        ];
    }

    private function radarVideo($data)
    {
        return $this->playbackVideoRepository->create([
            'file_url' => $data['file_url'],
            'yj_data_id' => $data['yj_data_id'],
        ]);
    }

    private function radarImg(array $data): array | bool
    {
        if ($msg = $this->repository->findByFilter(['yj_data_id' => $data['yj_data_id']])) {
            if (!empty($this->warnRecordService->getList(['msg_id' => $msg->id])->toArray()))
                return false;
            return [
                'type' => $this->getType($data['msg_type'], 1),
                'device_serial' => $data['device_serial'],
                'channel_no' => $data['channel_no'],
                'id' => $msg->id
            ];
        }
        $data['type'] = 1;
        $insert = $this->create($data);
        return [
            'type' => $this->getType($data['msg_type'], 1),
            'device_serial' => $data['device_serial'],
            'channel_no' => $data['channel_no'],
            'id' => $insert->id
        ];
    }

    private function getType(string $msgType, int $type)
    {
        if ($type = $this->alarmTypeRepository->findByFilter(['name' => $msgType, 'type' => $type])) {
            return $type->id;
        }
        return 0;
    }
}